#include "StdAfx.h"
#include "DBSocket.h"
#include "World.h"
#include "../GameDefine/Buffer.h"

CodesHandler<DBSocket> worlddbsessiontable[NS_Type_Nums] =
{
	{"DS_PlayerAuthSession", DS_PlayerAuthSession, &DBSocket::HandlePlayerAuthResult}
};

void DBSocket::ExecuteOpcode(tagMessage* m)
{
	if(m->dwHDCode<NS_Type_Nums)
		(this->*(worlddbsessiontable[m->dwHDCode].handler))(m);
	else
	{
		assert(0);
		sLog.Write("code is over");
	}
}

DBSocket	sDBSocket;
DBSocket& DBSocket::Inst()
{
	return sDBSocket;
}
DBSocket::DBSocket(void)
{
	m_pDBMsgList = new CListMsg;
	m_pBuffer = new CBuffer;
}
bool DBSocket::Init()
{
	m_bRun = true;
	m_hRecvDBMsg = CreateThread(NULL, 0, RecvDBMsgThread, this, 0, NULL);
	m_hConnectDB = CreateThread(NULL, 0, ConnectDBThread, this, 0, NULL);
	return 1;
}

DBSocket::~DBSocket(void)
{
	
}
bool DBSocket::Stop()
{
	closesocket(m_Sock);
	m_bRun = false;
	WaitForSingleObject(m_hRecvDBMsg, INFINITE);
	WaitForSingleObject(m_hConnectDB, INFINITE);
	delete m_pDBMsgList; m_pDBMsgList = NULL;
	delete m_pBuffer; m_pDBMsgList=NULL;
	return 1;
}

DWORD DBSocket::ConnectDBThread(LPVOID lp)
{
	DBSocket* pThis = (DBSocket*)lp;
	pThis->m_Sock = socket(AF_INET, SOCK_STREAM, 0);
	if (pThis->m_Sock == INVALID_SOCKET)
	{
		assert(0);
		return -1;
	}
	SOCKADDR_IN ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	ServerAddr.sin_port = htons(8081);
	while(pThis->m_bRun)
	{
		int iResult = connect(pThis->m_Sock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));
		if (iResult == 0)
		{
			IMSG(_T("Connect DB successful"));
			break;
		}
		Sleep(500);
	}
	return 0;
}

DWORD DBSocket::RecvDBMsgThread(LPVOID lp)
{
	DBSocket* pThis = (DBSocket*)lp;
	char buff[512] = {0};
	int	 iRst = 0;
	WaitForSingleObject(pThis->m_hConnectDB, INFINITE);
	while(pThis->m_bRun)
	{		
		iRst = recv(pThis->m_Sock, buff, sizeof(buff), 0);
 		if (iRst == SOCKET_ERROR)
 		{
 			IMSG(_T("db socket error"));
 			return 0;
 		}
		else if (iRst == 0)
		{
			IMSG(_T("db server sotp service"));
			return 0;
		}
 		else if (iRst>0)
 		{
 			pThis->m_pBuffer->Write(buff, iRst);
 			while(1)
 			{
 				if(pThis->m_pBuffer->TestRead(buff, 4) == 0) break;
 				short nLen;
 				memcpy(&nLen, buff, 4);
 				if (nLen > pThis->m_pBuffer->GetLength()) break;
 
 				NEW_MSG(lpMsg, nLen);
 				pThis->m_pBuffer->Read((char*)lpMsg, nLen);
 				pThis->m_pDBMsgList->AddMsg((tagMessage*)lpMsg, nLen);
 				DEL_MSG(lpMsg, nLen);
 			}
 		}
	}
	return 0;
}

void DBSocket::HandleDBMsg()
{
	tagMessage* pMsg = m_pDBMsgList->GetMsg();
	while(pMsg)
	{
		ExecuteOpcode(pMsg);
		DEL_MSG(pMsg, pMsg->dwSize);
		pMsg =m_pDBMsgList->GetMsg();
	}
}

int DBSocket::SendMSG2DB(void* lp, DWORD dwSize)
{
	DWORD nSize = dwSize;
	send(m_Sock, (char*)&nSize, 2, 0);
	return send(m_Sock, (char*)lp, dwSize, 0);
}


void DBSocket::HandlePlayerAuthResult(tagMessage* m)
{
	MSGTRANSLATE(p, m, DS_PlayerAuthSession);
	sWorld.HandleAuthSession(m);
}
